﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using AbstraX.Contracts;
using AbstraX.ServerInterfaces;
using ImpromptuInterface;
using SolutionFramework.Entities;
using AbstraX.TypeMappings;
using System.Data.Objects;
namespace SolutionFramework.Service
{
    public class AbstraXDatabaseProxy : IAbstraXDatabaseProxy
    {
        private SolutionFrameworkEntities entities;

        public AbstraXDatabaseProxy()
        {
            entities = new SolutionFrameworkEntities();
        }

        public string GetDocumentationSummary(Guid documentationID)
        {

           
            try
            {
                string summary;
                summary = this.entities.Documentations.Count().ToString() == "0" || documentationID == Guid.Empty ? (string.Empty) : (from p in this.entities.Documentations
                                                                                                                                      where (p.DocumentationID == documentationID)
                                                                                                                                      select p.DocumentationSummary).Single().ToString();

                return summary;
            }
            catch (System.Data.DataException ex)
            {
                throw ex;
            }
           
        }

        public List<IDbElement> GetAllElements()
        {
            List<IDbElement> list = new List<IDbElement>();
            var query = from p in this.entities.AbstraXElements
                        where (p.DeletedDate == null)
                        select p;

             foreach (var element in query)
            {

                list.Add(new
                {
                    DatabaseID = element.ID.ToString(),
                    ParentID = element.ParentID.ToString(),
                    Name = element.Name.ToString(),
                    ChildOrdinal = (float)element.ChildOrdinal,
                    DataType = (BaseType)null ,
                    DebugInfo = element.DebugInfo.ToString(),
                    Kind = DefinitionKind.NotApplicable,
                    DesignComments = element.DesignComments.ToString(),
                    Documentation = element.Documentation.ToString(),
                    DocumentationSummary = GetDocumentationSummary(element.DocumentationID == null ? Guid.Empty : element.DocumentationID.Value),
                    FolderKeyPair = element.FolderKeyPair.ToString(),
                    ImageURL = element.ImageURL.ToString(),
                    Facets = new Facet[0],
                    IsContainer = false,
                    AllowableContainerTypes = ContainerType.NotSet,
                    AllowableConstructTypes = ConstructType.NotSet,
                    DefaultConstructType = ConstructType.NotSet,
                    DefaultContainerType = ContainerType.NotSet,
                    Modifiers = Modifiers.Unknown,
                    RelatedID = element.RelatedID,
                    HasDocumentation = element.DocumentationID == null ? false : true

                }.ActLike<IDbElement>());

            }

            return list;        
        }

        public List<IDbElement> GetChildElements(string parentID)
        {
            List<IDbElement> list = new List<IDbElement>();
            var query = from p in this.entities.AbstraXElements
                        where (p.ParentID == parentID && p.DeletedDate == null)
                        select p;

            foreach (var element in query)
            {

                list.Add(new
                {
                    DatabaseID = element.ID.ToString(),
                    ParentID = element.ParentID.ToString(),
                    Name = element.Name.ToString(),
                    ChildOrdinal = (float)element.ChildOrdinal,
                    DataType = (BaseType)null,
                    DebugInfo = element.DebugInfo.ToString(),
                    Kind = DefinitionKind.NotApplicable,
                    DesignComments = element.DesignComments.ToString(),
                    Documentation = element.Documentation.ToString(),
                    DocumentationSummary = GetDocumentationSummary(element.DocumentationID == null ? Guid.Empty : element.DocumentationID.Value),
                    FolderKeyPair = element.FolderKeyPair.ToString(),
                    ImageURL = element.ImageURL.ToString(),
                    Facets = new Facet[0],
                    IsContainer = false,
                    AllowableContainerTypes = ContainerType.NotSet,
                    AllowableConstructTypes = ConstructType.NotSet,
                    DefaultConstructType = ConstructType.NotSet,
                    DefaultContainerType = ContainerType.NotSet,
                    Modifiers = Modifiers.Unknown,
                    RelatedID = element.RelatedID,
                    HasDocumentation = element.DocumentationID == null ? false : true

                }.ActLike<IDbElement>());

            }

            return list;
        }


        
        public List<IDbAttribute> GetAllAttributes()
        {

            List<IDbAttribute> list = new List<IDbAttribute>();

            var query = from p in this.entities.AbstraXAttributes 
                        where (p.DeletedDate == null)
                        select p;

            foreach (var attribute in query)
            {

                list.Add(new

                {

                    DatabaseID = attribute.ID.ToString(),
                    ParentID = attribute.ParentID.ToString(),
                    Name = attribute.Name.ToString(),
                    ChildOrdinal = (float)attribute.ChildOrdinal,
                    DataType = (BaseType)null,
                    DebugInfo = attribute.DebugInfo.ToString(),
                    Kind = DefinitionKind.NotApplicable,
                    DesignComments = attribute.DesignComments.ToString(),
                    Documentation = attribute.Documentation.ToString(),
                    DocumentationSummary = GetDocumentationSummary(attribute.DocumentationID == null ? Guid.Empty : attribute.DocumentationID.Value),
                    FolderKeyPair = attribute.FolderKeyPair.ToString(),
                    ImageURL = attribute.ImageURL.ToString(),
                    Facets = new Facet[0],
                    IsContainer = false,
                    AllowableContainerTypes = ContainerType.NotSet,
                    AllowableConstructTypes = ConstructType.NotSet,
                    DefaultConstructType = ConstructType.NotSet,
                    DefaultContainerType = ContainerType.NotSet,
                    Modifiers = Modifiers.Unknown,
                    RelatedID = attribute.RelatedID,
                    DocumentationID = attribute.DocumentationID,
                    HasDocumentation = attribute.DocumentationID == null ? false : true

                }.ActLike<IDbAttribute>());


            }

            return list;

        }

        public List<IDbElement> GetChildOfNavigationEntities(string relatedID)
        {
            List<IDbElement> list = new List<IDbElement>();
            var query = from p in this.entities.AbstraXElements
                        where (p.ID == new Guid(relatedID) && p.DeletedDate == null)
                        select p;

            foreach (var element in query)
            {

                list.Add(new
                {

                    DatabaseID = element.ID.ToString(),
                    ParentID = element.ParentID.ToString(),
                    Name = element.Name.ToString(),
                    ChildOrdinal = (float)element.ChildOrdinal,
                    DataType = (BaseType)null,
                    DebugInfo = element.DebugInfo.ToString(),
                    Kind = DefinitionKind.NotApplicable,
                    DesignComments = element.DesignComments.ToString(),
                    Documentation = element.Documentation.ToString(),
                    DocumentationSummary = GetDocumentationSummary(element.DocumentationID == null ? Guid.Empty : element.DocumentationID.Value),
                    FolderKeyPair = element.FolderKeyPair.ToString(),
                    ImageURL = element.ImageURL.ToString(),
                    Facets = new Facet[0],
                    IsContainer = false,
                    AllowableContainerTypes = ContainerType.NotSet,
                    AllowableConstructTypes = ConstructType.NotSet,
                    DefaultConstructType = ConstructType.NotSet,
                    DefaultContainerType = ContainerType.NotSet,
                    Modifiers = Modifiers.Unknown,
                    RelatedID = element.RelatedID,
                    HasDocumentation = element.DocumentationID == null ? false : true

                }.ActLike<IDbElement>());

            }

            return list;
        }

        public string GetRelatedNodeID(string ID)
        {
            string NodeID=string.Empty;
            try
            {

                var query = from p in this.entities.AbstraXElements
                            where (p.RelatedID == ID && p.DeletedDate == null)
                            select p;
                foreach (var element in query)
                {
                    NodeID = element.ID.ToString();
                }
            }
            catch (Exception Exception)
            {
                throw;
            }

            return NodeID;
        }

        public List<IDbAttribute> GetAttributes(string parentID)
        {
            List<IDbAttribute> list = new List<IDbAttribute>();
            var query = from p in this.entities.AbstraXAttributes
                        where (p.ParentID == parentID && p.DeletedDate == null)
                        select p;

            foreach (var attribute in query)
            {

                list.Add(new
                {

                    DatabaseID = attribute.ID.ToString(),
                    ParentID = attribute.ParentID.ToString(),
                    Name = attribute.Name.ToString(),
                    ChildOrdinal = (float)attribute.ChildOrdinal,
                    DataType = (ScalarType)null,
                    DebugInfo = attribute.DebugInfo.ToString(),
                    Kind = DefinitionKind.NotApplicable,
                    DesignComments = attribute.DesignComments.ToString(),
                    Documentation = attribute.Documentation.ToString(),
                    DocumentationSummary = GetDocumentationSummary(attribute.DocumentationID == null ? Guid.Empty : attribute.DocumentationID.Value),
                    FolderKeyPair = attribute.FolderKeyPair.ToString(),
                    ImageURL = attribute.ImageURL.ToString(),
                    Facets = new Facet[0],
                    Modifiers = Modifiers.Unknown,
                    DefaultValue = string.Empty,
                    RelatedID = attribute.RelatedID
                                       

                }.ActLike<IDbAttribute>());

            }

            return list;
        }

        public List<IDbOperation> GetOperations(string parentID)
        {
            throw new NotImplementedException();
        }

        public List<Facet> GetFacets(string parentID)
        {
            throw new NotImplementedException();
        }

        public BaseType GetBaseType(string parentID)
        {
            throw new NotImplementedException();
        }

        public ICustomFields GetCustomFields(string parentID)
        {

            return new AbstraXCustomFields(entities, parentID);
        }



        public string AddNewAttribute(IAttribute attribute)
        {
            var entity = new AbstraXAttribute
            {
                Name = attribute.Name,
                ChildOrdinal = (float?)attribute.ChildOrdinal,
                //DataType = attribute.DataType == null ? null : attribute.DataType.TypeCode.ToString(),
                DebugInfo = attribute.DebugInfo,
                //DefinitionKind = (byte)(attribute.Kind),
                DesignComments = attribute.DesignComments,
                Documentation = attribute.Documentation,
                FolderKeyPair = attribute.FolderKeyPair,
                ParentID = attribute.ParentID,
                ImageURL = attribute.ImageURL

            };
            try
            {
                entities.AbstraXAttributes.AddObject(entity);
                entities.SaveChanges();

            }
            catch (System.Data.UpdateException ex)
            {
                throw;
            }
            return entity.ID.ToString();
        }

        public string AddNewElement(IDbElement element)
        {
            var entity = new AbstraXElement
            {
                Name = element.Name,
                //AllowableConstructType = Convert.ToByte(element.AllowableConstructTypes),
                //AllowableContainerTypes = Convert.ToByte(element.AllowableContainerTypes),
                ChildOrdinal = element.ChildOrdinal,
                //DataType = element.DataType == null ? null : element.DataType.ToString(),
                DebugInfo = element.DebugInfo,
                //DefinitionKind = (byte)element.Kind,
                DesignComments = element.DesignComments,
                Documentation = element.Documentation,
                FolderKeyPair = element.FolderKeyPair,
                ParentID = element.ParentID,
                ImageURL = element.ImageURL,
                RelatedID = element.RelatedID == "" ? null : element.RelatedID
                //IsContainer = element.IsContainer
            };
            try
            {
                this.entities.AbstraXElements.AddObject(entity);
                this.entities.SaveChanges();
            }
            catch (System.Data.UpdateException ex)
            {
                throw;
            }
            return entity.ID.ToString();
        }

        public string AddNewNavElement(IDbElement element)
        {
            var entity = new AbstraXElement
            {

                Name = element.Name,
                //AllowableConstructType = Convert.ToByte(element.AllowableConstructTypes),
                //AllowableContainerTypes = Convert.ToByte(element.AllowableContainerTypes),
                ChildOrdinal = element.ChildOrdinal,
                //DataType = element.DataType == null ? null : element.DataType.ToString(),
                DebugInfo = element.DebugInfo,
                //DefinitionKind = (byte)element.Kind,
                DesignComments = element.DesignComments,
                Documentation = element.Documentation,
                FolderKeyPair = element.FolderKeyPair,
                ParentID = element.ParentID,
                ImageURL = element.ImageURL,
                RelatedID = element.RelatedID
                //IsContainer = element.IsContainer
            };
            try
            {
                this.entities.AbstraXElements.AddObject(entity);
                this.entities.SaveChanges();
            }
            catch (System.Data.UpdateException ex)
            {
                throw;
            }
            return entity.ID.ToString();
        }

        public string AddNewOperation(IOperation operation)
        {
            var entity = new AbstraXOperation
            {

                Name = operation.Name,
                ChildOrdinal = operation.ChildOrdinal,
                DebugInfo = operation.DebugInfo,
                DefinitionKind = (byte)operation.Kind,
                DesignComments = operation.DesignComments,
                Direction = (byte)operation.Direction,
                Documentation = operation.Documentation,
                FolderKeyPair = operation.FolderKeyPair,
                ParentID = operation.ParentID,
                ImageURL = operation.ImageURL
            };
            try
            {
                this.entities.AbstraXOperations.AddObject(entity);
                this.entities.SaveChanges();

            }
            catch (Exception ex)
            {
                System.Windows.Forms.MessageBox.Show(ex.InnerException.Message);
            }
            return entity.ID.ToString();
        }

        public string AddNewCustomFields(string parentID, string name, string fieldValue)
        {
            AbstraXCustomFields customObject = new AbstraXCustomFields(entities, parentID);
            customObject[name] = fieldValue;
            return customObject[name];
        }

        public void UpdateAttribute(IAttribute attribute, string oldName)
        {
            try
            {
                AbstraXAttribute query = this.entities.AbstraXAttributes.Single(p => p.ParentID == (attribute.ParentID) && p.Name == oldName);

                query.Name = attribute.Name;
                query.ChildOrdinal = (float)attribute.ChildOrdinal;
                //query.DataType = attribute.DataType == null ? null : attribute.DataType.ToString();
                query.DebugInfo = attribute.DebugInfo;
                //DefinitionKind = Convert.ToByte(attribute.Kind),
                query.DesignComments = attribute.DesignComments;
                query.Documentation = attribute.Documentation;
                query.FolderKeyPair = attribute.FolderKeyPair;
                query.ParentID = attribute.ParentID;
                query.ImageURL = attribute.ImageURL;
                this.entities.SaveChanges();
            }
            catch (System.Data.UpdateException ex)
            {
                throw;
            }
        }
        public void UpdateElement(string entityID, string newName)
        {
            try
            {
                AbstraXElement query = this.entities.AbstraXElements.Single(p => p.ID == new Guid(entityID));
                query.Name = newName;                
                this.entities.SaveChanges();
            }
            catch (System.Data.UpdateException ex)
            {
                throw;
            }
        }

        public void UpdateNavigationProperty(string ID, string nodeText)
        {
            try
            {
                AbstraXElement query = this.entities.AbstraXElements.Single(p => p.ID == new Guid(ID));
                query.Name = nodeText;
                this.entities.SaveChanges();

            }
            catch (System.Data.UpdateException ex)
            {

                throw;
            }
        }

        public void UpdateOperation(IOperation operation)
        {
            try
            {
                AbstraXOperation query = this.entities.AbstraXOperations.Single(p => p.ID == Guid.Parse(operation.ID));
                query.Name = operation.Name;
                query.ChildOrdinal = operation.ChildOrdinal;
                query.DebugInfo = operation.DebugInfo;
                query.DefinitionKind = (byte)operation.Kind;
                query.DesignComments = operation.DesignComments;
                query.Direction = (byte)operation.Direction;
                query.Documentation = operation.Documentation;
                query.FolderKeyPair = operation.FolderKeyPair;
                query.ParentID = operation.ParentID;
                query.ImageURL = operation.ImageURL;
                this.entities.SaveChanges();
            }
            catch (System.Data.UpdateException ex)
            {
                throw;
            }
        }
        public void DeleteAttribute(IAttribute attribute)
        {

            AbstraXAttribute query = this.entities.AbstraXAttributes.Single(p => p.ParentID == (attribute.ParentID) && p.Name == attribute.Name);
            try
            {
                query.DeletedDate = DateTime.Now;
                this.entities.SaveChanges();
            }
            catch (System.Data.UpdateException ex)
            {
                throw;
            }
        }

        public void DeleteElement(IElement element)
        {

            try
            {
                AbstraXElement query = this.entities.AbstraXElements.Single(p => p.ParentID == (element.ParentID) && p.Name == element.Name);
                query.DeletedDate = DateTime.Now;
                this.entities.SaveChanges();
            }
            catch (System.Data.UpdateException ex)
            {
                throw;
            }
        }
        public void DeleteOperation(string ID)
        {
            AbstraXOperation a = this.entities.AbstraXOperations.Single(p => p.ID == Guid.Parse(ID));
            this.entities.AbstraXOperations.DeleteObject(a);
            try
            {
                this.entities.SaveChanges();
            }
            catch (System.Data.UpdateException ex)
            {
                throw;
            }
        }

        #region comments


        public string AddNewComments(string documentationSummary, string documentation)
        {

            
            var entity = new Documentation
            {
                DocumentationSummary = documentationSummary,
                Documentation1 = documentation
             };

            try
            {
                entities.Documentations.AddObject(entity);
                entities.SaveChanges();
               
            }
            catch (System.Data.UpdateException ex)
            {
                throw ex;
            }
            return entity.DocumentationID.ToString();
        }

        public string checkAttributeDocIDforAddComment(string id)
        {
            string attDocID;

            try
            {
                AbstraXAttribute query = this.entities.AbstraXAttributes.Single(p => p.ID == new Guid(id) && p.DeletedDate == null);
                attDocID = query.DocumentationID.ToString(); 
            }
            catch (System.Data.DataException ex)
            {
                throw ex;
            }
            return attDocID;
        }


        public string checkElementDocIDforAddComment(string id)
        {
            string eleDocID;

            try
            {
                AbstraXElement query = this.entities.AbstraXElements.Single(p => p.ID == new Guid(id) && p.DeletedDate == null);
                eleDocID = query.DocumentationID.ToString();
            }
            catch (System.Data.DataException ex)
            {
                throw ex;
            }
            return eleDocID;
        }

        public void AddAttributeDocumentaionID(string docID, string Id)
        {
            try
            {
                 AbstraXAttribute query = this.entities.AbstraXAttributes.Single(p => p.ID == new Guid(Id) && p.DeletedDate == null);
                 query.DocumentationID = Guid.Parse(docID);
                 this.entities.SaveChanges();
            }
            catch(System.Data.UpdateException ex)
            {
                throw ex;
            }
        }


        public void AddElementDocumentaionID(string docID, string Id)
        {
           try
            {
                AbstraXElement query = this.entities.AbstraXElements.Single(p => p.ID == new Guid(Id) && p.DeletedDate == null);
                query.DocumentationID = Guid.Parse(docID);
                this.entities.SaveChanges();
            }
            catch (System.Data.UpdateException ex)
            {
                throw ex;
            }
        }

        public string[] GetAttibuteComments(string ID)
        {
            
            string[] list = new string[2];
            try
            {
                AbstraXAttribute query = this.entities.AbstraXAttributes.Single(p => p.ID == new Guid(ID) && p.DeletedDate == null && p.RelatedID == null);

                Documentation doc = this.entities.Documentations.Single(p => p.DocumentationID == (query.DocumentationID == null ? Guid.Empty : query.DocumentationID.Value));
                list[0] = doc.Documentation1;// ToString();

                Documentation docSummary = this.entities.Documentations.Single(q => q.DocumentationID == (query.DocumentationID == null ? Guid.Empty : query.DocumentationID.Value));
                list[1] = docSummary.DocumentationSummary;//.Single().ToString();

            
            }
            catch(System.Data.UpdateException ex)
            {
                throw ex;
            }

            return list;
        }


        public string[] GetElementComments(string ID)
        {

            string[] list = new string[2];
            try
            {
                AbstraXElement query = this.entities.AbstraXElements.Single(p => p.ID == new Guid(ID) && p.DeletedDate == null && p.RelatedID == null);

                Documentation doc = this.entities.Documentations.Single(p => p.DocumentationID == (query.DocumentationID == null ? Guid.Empty : query.DocumentationID.Value));
                list[0] = doc.Documentation1;// ToString();

                Documentation docSummary = this.entities.Documentations.Single(q => q.DocumentationID == (query.DocumentationID == null ? Guid.Empty : query.DocumentationID.Value));
                list[1] = docSummary.DocumentationSummary;//.Single().ToString();

            }
            catch (System.Data.UpdateException ex)
            {
                throw ex;
            }

            return list;                     
        }



        public void GetAttibuteCommentDocIDtoDelete(string ID)
        {
            string attributeDocID;
            string docID;
            try
            {
                AbstraXAttribute query = this.entities.AbstraXAttributes.Single(p => p.ID == new Guid(ID) && p.DeletedDate == null);

                docID = query.DocumentationID.ToString();

                attributeDocID = query.DocumentationID.ToString();

                if (docID != null)
                {
                    Documentation doc = this.entities.Documentations.Single(p => p.DocumentationID == new Guid(docID) && p.DeletedDate == null);

                    this.entities.Documentations.DeleteObject(doc);

                    this.entities.SaveChanges();

                }
                if (attributeDocID != null)
                {
                    attributeDocID = null;
                }
                
                
            }
            catch (System.Data.UpdateException ex)
            {
                throw ex;
            }

         //   return docID;
        }


        public void GetElementCommentDocIDtoDelete(string ID)
        {
            string elementDocID;
            string docID;
            try
            {
                AbstraXElement query = this.entities.AbstraXElements.Single(p => p.ID == new Guid(ID) && p.DeletedDate == null);

                docID = query.DocumentationID.ToString();

                elementDocID  = query.DocumentationID.ToString();

                if (docID != null)
                {
                    Documentation doc = this.entities.Documentations.Single(p => p.DocumentationID == new Guid(docID) && p.DeletedDate == null);

                    this.entities.Documentations.DeleteObject(doc);

                    this.entities.SaveChanges();
                }

                if (elementDocID != null)
                {
                    elementDocID = null;
                }

            }
            catch (System.Data.UpdateException ex)
            {
                throw ex;
            }

          //  return docID;
        }


        public void UpdateComments(string id, string documentationSummary, string documentation)
        {
            try
            {
                Documentation query = this.entities.Documentations.Single(p => p.DocumentationID == new Guid(id) && p.DeletedDate == null);
           
                query.DocumentationSummary  = documentationSummary;
                query.Documentation1 = documentation;
                this.entities.SaveChanges();
            
            }
            catch (System.Data.UpdateException ex)
            {
                throw ex;
            }
         }


        #endregion
        

    }

}
